﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Windows;

namespace YSCommander.Data
{
	/// <summary>
	/// Contains program details.
	/// </summary>
	public class Program
	{
		#region Constants

		public const String ElementProgram = "Program";
		private const String ElementProgramName = "ProgramName";
		private const String ElementLocation = "Location";
		private const String ElementParameters = "Parameters";
		private const String ElementScript = "Script";
		private const String ElementStartFolder = "StartFolder";
		private const String ElementIsOpenWindow = "IsOpenWindow";
		private const String ElementProgramType = "ProgramType";
		#endregion Constants

		#region Fields
		#endregion Fields

		#region Properties

		/// <summary>
		/// Gets or sets the program name.
		/// </summary>
		public String ProgramName
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the full path to the program
		/// </summary>
		public String Location
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the execution start folder.
		/// </summary>
		public String StartFolder
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the execution program parameters.
		/// </summary>
		public String Parameters
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the execution mode with opened or closed window.
		/// </summary>
		public bool IsOpenWindow
		{
			get;
			set;
		}

		#endregion Properties

		/// <summary>
		/// Gets or sets the script content.
		/// </summary>
		public String Script
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the program type.
		/// </summary>
		public YSCommander.Data.ProgramType ProgramType
		{
			get;
			set;
		}

		#region Methods

		/// <summary>
		/// CreraTes the new instance.
		/// </summary>
		public Program()
		{
			ProgramName = String.Empty;
			Location = String.Empty;
			Parameters = String.Empty;
			StartFolder = String.Empty;
			IsOpenWindow = true;
			ProgramType = ProgramType.Program;
			Script = String.Empty;
		}

		/// <summary>
		/// Copy ctor.
		/// </summary>
		/// <param name="program"></param>
		public Program(Program program)
		{
			ProgramName = program.ProgramName;
			Location = program.Location;
			Parameters = program.Parameters;
			StartFolder = program.StartFolder;
			IsOpenWindow = program.IsOpenWindow;
			ProgramType = program.ProgramType;
			Script = program.Script;
		}

		/// <summary>
		/// Creates element with serialized program data.
		/// </summary>
		/// <param name="doc">XML document where to create element.</param>
		/// <returns>New element with serialized program data.</returns>
		public IXPathNavigable Serialize(IXPathNavigable doc)
		{
			XmlDocument xmlDocument = doc as XmlDocument;
			XmlElement program = xmlDocument.CreateElement(ElementProgram);

			XmlElement e = xmlDocument.CreateElement(ElementProgramName);
			e.InnerText = ProgramName;
			program.AppendChild(e);

			e = xmlDocument.CreateElement(ElementLocation);
			e.InnerText = Location;
			program.AppendChild(e);

			e = xmlDocument.CreateElement(ElementParameters);
			e.InnerText = Parameters;
			program.AppendChild(e);

			e = xmlDocument.CreateElement(ElementScript);
			e.InnerText = Script;
			program.AppendChild(e);

			e = xmlDocument.CreateElement(ElementStartFolder);
			e.InnerText = StartFolder;
			program.AppendChild(e);

			e = xmlDocument.CreateElement(ElementIsOpenWindow);
			e.InnerText = IsOpenWindow.ToString();
			program.AppendChild(e);

			e = xmlDocument.CreateElement(ElementProgramType);
			e.InnerText = ProgramType.ToString();
			program.AppendChild(e);

			return program;
		}

		/// <summary>
		/// Extarcts program data.
		/// </summary>
		/// <param name="program">XML elemnt with data.</param>
		public void Deserialize(IXPathNavigable program)
		{
			XmlNode n = null;
			XmlNode programNode = program as XmlNode;
			try
			{
				n = programNode.SelectSingleNode("./" + ElementProgramName);
				if (null != n)
				{
					ProgramName = n.InnerText;
				}

				n = programNode.SelectSingleNode("./" + ElementLocation);
				if (null != n)
				{
					Location = n.InnerText;
				}

				n = programNode.SelectSingleNode("./" + ElementParameters);
				if (null != n)
				{
					Parameters = n.InnerText;
				}

				n = programNode.SelectSingleNode("./" + ElementScript);
				if (null != n)
				{
					Script = n.InnerText;
				}

				n = programNode.SelectSingleNode("./" + ElementStartFolder);
				if (null != n)
				{
					StartFolder = n.InnerText;
				}

				n = programNode.SelectSingleNode("./" + ElementIsOpenWindow);
				if (null != n)
				{
					IsOpenWindow = Boolean.Parse(n.InnerText);
				}

				n = programNode.SelectSingleNode("./" + ElementProgramType);
				if (null != n)
				{
					ProgramType = (ProgramType)Enum.Parse(typeof(ProgramType), n.InnerText, true);
				}
			}
			catch (XPathException excp)
			{
				MessageBox.Show(String.Format(CultureInfo.InvariantCulture,
						"Can't save data: {0}", excp.Message),
						Assembly.GetExecutingAssembly().GetName().Name, 
						MessageBoxButton.OK, MessageBoxImage.Error);
			}
		}

		#region Overrides

		/// <summary>
		/// Checks, if an object is Program and if it has same name.
		/// </summary>
		/// <param name="obj">An object to compare.</param>
		/// <returns>True, if an object is Program and if it has same name.</returns>
		public override bool Equals(object obj)
		{
			bool isEqual = false;
			Program theProgram = obj as Program;

			if (null != theProgram)
			{
				isEqual = ProgramName.Equals(theProgram.ProgramName);
			}

			return isEqual;
		}

		/// <summary>
		/// Gets the hash code as ProgramName's hash code.
		/// </summary>
		/// <returns>the hash code as ProgramName's hash code.</returns>
		public override int GetHashCode()
		{
			return ProgramName.GetHashCode();
		}

		/// <summary>
		/// Gets the text representation of the object.
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			StringBuilder sb = new StringBuilder();
			sb.Append("Program:");

			sb.AppendFormat(" ProgramName: {0}", ProgramName.ToString());
			sb.AppendFormat(", Location: {0}", Location.ToString());
			sb.AppendFormat(", Start folder: {0}", StartFolder.ToString());
			sb.AppendFormat(", Parameters: {0}", Parameters.ToString());
			sb.AppendFormat(", IsOpenWindow: {0}", IsOpenWindow.ToString());
			sb.AppendFormat(", ProgramType: {0}", ProgramType.ToString());
			sb.AppendFormat(", Script: {0}", Script.ToString());

			return sb.ToString();
		}
		#endregion Overrides

		#endregion Methods
	}
}
